﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;

namespace Dapper.Library.SqlContainer
{
    /// <summary>
    /// 数据库配置操作对象
    /// </summary>
    public class DatabaseManager
    {
        #region 变量

        /// <summary>
        /// 同步锁对象
        /// </summary>
        private static readonly object locker = new object();

        /// <summary>
        /// 配置文件全路径
        /// </summary>
        private static string fileConfigFullName;

        /// <summary>
        /// 映射文件全路径
        /// </summary>
        private static string directoryFullPath;

        /// <summary>
        /// 数据库实例配置
        /// </summary>
        private static List<DatabaseInstance> databaseInstances;

        /// <summary>
        /// 侦听文件系统对象
        /// </summary>
        private static FileSystemWatcher sWatcher = new FileSystemWatcher()
        {
            NotifyFilter = NotifyFilters.CreationTime | NotifyFilters.LastWrite
        };

        /// <summary>
        /// 配置文件的路径名
        /// </summary>
        private const string fileConfigPath = @"Config\Database\files.config.json";

        /// <summary>
        /// 文件存放的文件夹路径
        /// </summary>
        private const string directoryPath = @"Config\Database\";

        #endregion

        static DatabaseManager()
        {
            try
            {
                string rootDic = string.Empty;

                try
                {
                    rootDic = AppContext.BaseDirectory;
                }
                catch
                {
                    rootDic = AppDomain.CurrentDomain.BaseDirectory;
                }

                fileConfigFullName = string.Format("{0}{1}", rootDic, fileConfigPath);
                directoryFullPath = string.Format("{0}{1}", rootDic, directoryPath);

                sWatcher.Changed += (s, e) => { InitDatabaseList(); };
                sWatcher.Path = Path.GetDirectoryName(directoryFullPath);
                InitDatabaseList();
                sWatcher.EnableRaisingEvents = true;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        /// <summary>
        /// 获取数据库配置实例
        /// </summary>
        /// <param name="name"></param>
        /// <returns>处理结果</returns>
        public static DatabaseInstance GetDatabase(string name)
        {
            return databaseInstances.Find(p=>p.Name.Equals(name));
        }

        /// <summary>
        /// 初始化数据库配置集合
        /// </summary>
        private static void InitDatabaseList()
        {
            lock (locker)
            {
                try
                {
                    databaseInstances = new List<DatabaseInstance>();

                    // 获取命令集合
                    var files = GetDataCommandFileList();

                    DatabaseInstances instances = null;

                    foreach (var fileInstance in files.InstanceList)
                    {
                        instances = $"{directoryFullPath}{fileInstance.FilePath}".FileToObject<DatabaseInstances>();

                        if (instances == null) continue;

                        foreach (var commandInstance in instances.InstanceList)
                        {
                            var count = databaseInstances.Count(p => p.Name.Equals(commandInstance.Name));
                            if (count > 1)
                            {
                                throw new AggregateException("已经加入相同的键:" + commandInstance.Name);
                            }
                            else
                            {
                                databaseInstances.Add(commandInstance);
                            }
                        }
                    }
                }
                catch (Exception ex)
                {
                    throw ex;
                }
            }
        }

        /// <summary>
        /// 获取命令文件
        /// </summary>
        /// <returns>命令文件集合</returns>
        private static ConfigFiles GetDataCommandFileList()
        {
            return fileConfigFullName.FileToObject<ConfigFiles>();
        }
    }
}
